package com.babel.util.util;


import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

/**
 * @author sylorl
 */
public final class DateUtils {
    public static Date date(int year, int month, int day) {
        return date(year, month, day, 0, 0, 0);
    }

    public static Date date(int year, int month, int day, int hour, int minute, int second) {
        Calendar calendar = Calendar.getInstance();
        calendar.setLenient(false);
        calendar.set(year, month, day, hour, minute, second);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    public static Calendar calendar(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar;
    }

    public static Date add(Date date, int field, int value) {
        Calendar calendar = calendar(date);
        calendar.add(field, value);
        return calendar.getTime();
    }

    public static int get(Date date, int field) {
        Calendar calendar = calendar(date);
        return calendar.get(field);
    }

    public static Date withField(Date date, int field, int value) {
        Calendar calendar = calendar(date);
        calendar.set(field, value);
        return calendar.getTime();
    }

    public static int getYear(Date date) {
        return get(date, Calendar.YEAR);
    }

    public static int getMonth(Date date) {
        return get(date, Calendar.MONTH);
    }

    public static int getDay(Date date) {
        return get(date, Calendar.DATE);
    }

    public static int getHour(Date date) {
        return get(date, Calendar.HOUR_OF_DAY);
    }

    public static int getMinute(Date date) {
        return get(date, Calendar.MINUTE);
    }

    public static Date withHour(Date date, int value) {
        return withField(date, Calendar.HOUR_OF_DAY, value);
    }

    public static Date withMinute(Date date, int value) {
        return withField(date, Calendar.MINUTE, value);
    }

    public static Date toCurrentTimeZone(Date targetDate, TimeZone targetTimeZone) {
        Calendar target = calendar(targetDate);

        Calendar result = Calendar.getInstance(targetTimeZone);
        result.set(Calendar.YEAR, target.get(Calendar.YEAR));
        result.set(Calendar.MONTH, target.get(Calendar.MONTH));
        result.set(Calendar.DATE, target.get(Calendar.DATE));
        result.set(Calendar.HOUR_OF_DAY, target.get(Calendar.HOUR_OF_DAY));
        result.set(Calendar.MINUTE, target.get(Calendar.MINUTE));
        result.set(Calendar.SECOND, target.get(Calendar.SECOND));
        result.set(Calendar.MILLISECOND, target.get(Calendar.MILLISECOND));

        return result.getTime();
    }

    public static boolean isWeekDay(Date targetDate) {
        Calendar calendar = calendar(targetDate);
        int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
        return dayOfWeek != Calendar.SATURDAY && dayOfWeek != Calendar.SUNDAY;
    }

    public static boolean isDateValid(int year, int month, int day) {
        try {
            date(year, month, day);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    public static Date truncateTime(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    public static Date parseDate(String datestr) {
    	if(StringUtils.isBlank(datestr)) {
    		return null;
    	}
    	try {
			return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(datestr);
		} catch (ParseException e) {
			throw new IllegalArgumentException(String.format("The input date string(%s) is not valid.", datestr), e);
		}
    }
    
    public static String formatDate(Date date) {
    	return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);
    }
    
    public static String formatDate(Date date, String format) {
    	return new SimpleDateFormat(format).format(date);
    }
    
	/**
	 * 计算两个日期之间相差的天数
	 * 
	 * @param smdate 较小的时间
	 * @param bdate 较大的时间
	 * @return 相差天数
	 * @throws IllegalArgumentException
	 */
	public static int daysBetween(Date smdate, Date bdate) {
		try {
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
			smdate = sdf.parse(sdf.format(smdate));
			bdate = sdf.parse(sdf.format(bdate));
			Calendar cal = Calendar.getInstance();
			cal.setTime(smdate);
			long time1 = cal.getTimeInMillis();
			cal.setTime(bdate);
			long time2 = cal.getTimeInMillis();
			long between_days = (time2 - time1) / (1000 * 3600 * 24);

			return Integer.parseInt(String.valueOf(between_days));
		} catch (ParseException e) {
			throw new IllegalArgumentException(String.format("The input date string(%s) string(%s) is not valid.", smdate, bdate), e);
		}
	}
    public static Date updateToCurrentYMD(Date date) {
    	Calendar current = Calendar.getInstance();
    	
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.YEAR, current.get(Calendar.YEAR));
        cal.set(Calendar.MONTH, current.get(Calendar.MONTH));
        cal.set(Calendar.DAY_OF_MONTH, current.get(Calendar.DAY_OF_MONTH));
        return cal.getTime();
    }
	public static int compareTo(Date smdate, Date bgdate,String format) {
		
		try {
			SimpleDateFormat sdf = new SimpleDateFormat(format);
			smdate = sdf.parse(sdf.format(smdate));
			bgdate = sdf.parse(sdf.format(bgdate));
			Calendar cal = Calendar.getInstance();
			cal.setTime(smdate);
			long sm = cal.getTimeInMillis();
			cal.setTime(bgdate);
			long bg = cal.getTimeInMillis();
			
			if(sm < bg){
				return 1;
			}else if(sm == bg){
				return 0;
			}else {
				return -1;
			}
		} catch (ParseException e) {
			throw new IllegalArgumentException(String.format("The input date string(%s) string(%s) is not valid.", smdate, bgdate), e);
		}
	}
    
	/**
	   * 当天的开始时间
	   * @return
	   */
	  public static Date startOfTodDay(Date date) {
	    Calendar calendar = Calendar.getInstance();
	    calendar.setTime(date);
	    calendar.set(Calendar.HOUR_OF_DAY, 0);
	    calendar.set(Calendar.MINUTE, 0);
	    calendar.set(Calendar.SECOND, 0);
	    calendar.set(Calendar.MILLISECOND, 0);
	    return calendar.getTime();
	  }
	  
	  /**
	   * 当天的结束时间
	   * @return
	   */
	  public static Date endOfTodDay(Date date) {
	    Calendar calendar = Calendar.getInstance();
	    calendar.setTime(date);
	    calendar.set(Calendar.HOUR_OF_DAY, 23);
	    calendar.set(Calendar.MINUTE, 59);
	    calendar.set(Calendar.SECOND, 59);
	    calendar.set(Calendar.MILLISECOND, 999);
	    return calendar.getTime();
	  }
    private DateUtils() {
    }
    
    private static final long ONE_MINUTE = 60000L;
	private static final long ONE_HOUR = 3600000L;
	private static final long ONE_DAY = 86400000L;
	private static final long ONE_WEEK = 604800000L;

	private static final String ONE_SECOND_AGO = "刚刚";
	private static final String ONE_MINUTE_AGO = "分钟前";
	private static final String ONE_HOUR_AGO = "小时前";
	private static final String ONE_DAY_AGO = "天前";
	private static final String ONE_MONTH_AGO = "月前";
	private static final String ONE_YEAR_AGO = "年前";

//	public static void main(String[] args) throws ParseException {
//		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//		Date date = format.parse("2016-07-28 15:47:09");
//		System.out.println(format(date));
//	}
	
	public static String getOldDayDesc(Date date){
		return format(date);
	}

	public static String format(Date date) {
		long delta = new Date().getTime() - date.getTime();
		int dayValues = daysBetween(date,new Date());
		if (delta <=1L * ONE_MINUTE) {
			//long seconds = toSeconds(delta);
			//return (seconds <= 0 ? 1 : seconds) + ONE_SECOND_AGO;
			return ONE_SECOND_AGO;
		}
		if (delta <=45L * ONE_MINUTE) {
			long minutes = toMinutes(delta);
			return (minutes <= 0 ? 1 : minutes) + ONE_MINUTE_AGO;
		}
		if (delta <=24L * ONE_HOUR) {
			long hours = toHours(delta);
			return (hours <= 0 ? 1 : hours) + ONE_HOUR_AGO;
		}
		if (delta <=48L * ONE_HOUR) {
			return "1"+ONE_DAY_AGO;
		}
		if (delta <=30L * ONE_DAY) {
			long days = toDays(delta);
			return (days <= 0 ? 1 : days) + ONE_DAY_AGO;
		}
		if(dayValues<=365){
			long months = toMonths(delta);
			return (months <= 0 ? 1 : months) + ONE_MONTH_AGO;
		}else{
			int years = dayValues/365;
			return (years <= 0 ? 1 : years) + ONE_YEAR_AGO;
		}
	}

	private static long toSeconds(long date) {
		return date / 1000L;
	}

	private static long toMinutes(long date) {
		return toSeconds(date) / 60L;
	}

	private static long toHours(long date) {
		return toMinutes(date) / 60L;
	}

	private static long toDays(long date) {
		return toHours(date) / 24L;
	}

	private static long toMonths(long date) {
		return toDays(date) / 30L;
	}

	private static long toYears(long date) {
		return toMonths(date) / 365L;
	}
}
